package com.yc.study.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.study.entity.StudentCheckInLog;
import com.yc.study.entity.User;
import com.yc.study.entity.UserRole;
import com.yc.study.mapper.StudentCheckInLogMapper;
import com.yc.study.mapper.UserMapper;
import com.yc.study.mapper.UserRoleMapper;
import com.yc.study.service.IUserService;
import com.yc.study.vo.ChangePasswordVo;
import com.yc.study.vo.RegisterVo;
import com.yc.study.vo.StudentCountVo;
import com.yc.study.vo.UserVo;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 服务实现类
 *
 * @author 王妍
 * @since 2022-02-20
 */
@Service
@AllArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

  private final PasswordEncoder passwordEncoder;

  private final UserRoleMapper userRoleMapper;

  private final UserMapper userMapper;

  private final StudentCheckInLogMapper studentCheckInLogMapper;

  @Override
  public User loadUserByUserName(String username) {
    return getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public User register(RegisterVo registerUser) {
    String username = registerUser.getUsername();
    User existedUser = getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
    if (existedUser != null) {
      throw new RuntimeException("用户名已经存在!");
    }
    final User user = new User();
    user.setUsername(username);
    user.setPassword(passwordEncoder.encode(registerUser.getPassword()));
    save(user);
    // 注册时绑定角色
    final UserRole userRole = new UserRole();
    userRole.setUserId(user.getId());
    userRole.setRoleId(registerUser.getRoleId());
    userRoleMapper.insert(userRole);
    return user;
  }

  @Override
  public void changePassword(String username, ChangePasswordVo changePasswordVo) {
    final Optional<User> user =
        Optional.ofNullable(getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username)));
    final String password =
        user.map(User::getPassword).orElseThrow(() -> new UsernameNotFoundException("用户不存在!"));
    if (passwordEncoder.matches(changePasswordVo.getOldPassword(), password)) {
      user.get().setPassword(passwordEncoder.encode(changePasswordVo.getPassword()));
      save(user.get());
    }
  }

  @Override
  public Page<UserVo> loadUserVoPage(Page<UserVo> page, UserVo userVo) {
    return userMapper.selectUserVoPage(page, userVo);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void saveInfo(UserVo userVo) {
    User user = new User();
    BeanUtils.copyProperties(userVo, user);
    // 用户不存在，先注册再更新
    if (userVo.getId() == null) {
      RegisterVo registerVo = new RegisterVo();
      registerVo.setUsername(userVo.getUsername());
      registerVo.setPassword(userVo.getPassword());
      user.setId(register(registerVo).getId());
    }
    saveOrUpdate(user);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void deleteAll(Long[] userIds) {
    removeByIds(Arrays.asList(userIds));
    userRoleMapper.delete(
        new LambdaQueryWrapper<UserRole>().in(UserRole::getUserId, Arrays.asList(userIds)));
  }

  @Override
  public List<User> loadTeacherList() {
    return userMapper.loadTeacherList();
  }

  @Override
  public Page<UserVo> loadUserVoPage2(Long taskId, Page<UserVo> page, UserVo userVo) {
    final Page<UserVo> userVoPage = userMapper.selectUserVoPage2(taskId, page, userVo);
    userVoPage.getRecords().forEach(student->{
      final List<StudentCheckInLog> studentCheckInLogs = studentCheckInLogMapper
              .selectList(new LambdaQueryWrapper<StudentCheckInLog>()
                      .eq(StudentCheckInLog::getStudentId, student.getId()));
      if(!studentCheckInLogs.isEmpty()){
        userVo.setStatus(true);
      }else{
        userVo.setStatus(false);
      }
    });
    return userVoPage;
  }

  @Override
  public StudentCountVo list2(Long taskId) {
    final Integer listIn = userMapper.listIn(taskId);
    final Integer listOut = userMapper.listOut(taskId);
    final StudentCountVo studentCountVo = new StudentCountVo();
    studentCountVo.setCheckIn(listIn);
    studentCountVo.setNoCheckIn(listOut);
    return studentCountVo;
  }
}
